package com.sinodata.bsm.cicp.collector.network;

import java.io.IOException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.snmp4j.CommunityTarget;
import org.snmp4j.Snmp;
import org.snmp4j.smi.GenericAddress;
import org.snmp4j.smi.OctetString;
import org.snmp4j.transport.DefaultUdpTransportMapping;

import com.sinodata.bsm.cicp.exception.CollectorException;
import com.sinodata.bsm.cicp.util.ProtocolParameterUtil;
import com.sinodata.bsm.cicp.util.snmp.GetData;
import com.sinodata.bsm.cicp.util.snmp.MibInterfaceEntry;
import com.sinodata.bsm.cicp.util.snmp.OMMappingInfo;
import com.sinodata.bsm.common.constants.SnmpConstants;
import com.sinodata.bsm.common.vo.ProtocolParameter;
import com.sinodata.bsm.common.vo.ResPropertyValue;
import com.sinodata.bsm.common.vo.ResPropertyValue.PropValue;

/**
 * <p>
 * Description: 
 * </p>
 *
 * @author wangpeng
 * @version 1.0

 * <p>
 * History: 
 *
 * Date                     Author         Version     Description
 * ---------------------------------------------------------------------------------
 * 2013-10-9 下午3:54:28          wangpeng        1.0         To create
 * </p>
 *
 * @since 
 * @see     
 */
public class InterfaceCollector extends NetWorkCollector {
    private static final Logger logger = Logger.getLogger(InterfaceCollector.class);

    private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#.##");

    private final Map<String, List<Long>> lastValueMap = new HashMap<String, List<Long>>();

    private Long lastTime = null;

    @Override
    public String[] getPropMeta() {
        //入流量(B)  ,出流量 (B)  ,发送错误包,接收错误包,发送丢弃包 ,接收丢弃包  ,发送带宽利用率,接收带宽利用率,工作状态
        return new String[] { "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9" };
    }

    @Override
    public String[] getParamMeta() {
        return null;
    }

    @Override
    public List<ResPropertyValue> collect(String ip) throws CollectorException {
        String community = "public";
        Integer port = 161;
        int version = 1;
        ProtocolParameter parameter = ProtocolParameterUtil.getSnmpValue(ip);
        if (parameter != null) {
            community = parameter.getUserName();
            port = parameter.getPort();
            version = SnmpConstants.getVersion(parameter.getProtocol());
        }
        Snmp snmp;
        try {
            snmp = new Snmp(new DefaultUdpTransportMapping());
            snmp.listen();
        } catch (IOException e) {
            throw new CollectorException(e);
        }
        List<ResPropertyValue> list = new ArrayList<ResPropertyValue>();
        CommunityTarget target = new CommunityTarget();
        target.setCommunity(new OctetString(community));
        target.setAddress(GenericAddress.parse("udp:" + ip.trim() + "/" + port));
        target.setRetries(retries);
        target.setTimeout(timeout);
        target.setVersion(version);
        try {
            String[] props = getPropMeta();
            List<OMMappingInfo> OMMappingInfo = GetData.getAllTableData(snmp, MibInterfaceEntry.class, target);
            long currentTime = System.currentTimeMillis();
            for (OMMappingInfo mapping : OMMappingInfo) {
                ResPropertyValue resPropertyValueX = new ResPropertyValue();
                list.add(resPropertyValueX);

                PropValue[] values = new ResPropertyValue.PropValue[props.length];
                resPropertyValueX.setValues(values);

                MibInterfaceEntry inter = (MibInterfaceEntry) mapping;
                int index = inter.getIfIndex();
                if (index == 0) {
                    continue;
                }

                String key = ip + "_" + index;
                resPropertyValueX.setInid(key);

                values[0] = ResPropertyValue.createPropValue(inter.getIfInOctets() / 1024 + "", props[0]);
                values[1] = ResPropertyValue.createPropValue(inter.getIfOutOctets() / 1024 + "", props[1]);
                values[2] = ResPropertyValue.createPropValue(inter.getIfOutErrors() + "", props[2]);
                values[3] = ResPropertyValue.createPropValue(inter.getIfInErrors() + "", props[3]);
                values[4] = ResPropertyValue.createPropValue(inter.getIfOutDiscards() + "", props[4]);
                values[5] = ResPropertyValue.createPropValue(inter.getIfInDiscards() + "", props[5]);
                values[8] = ResPropertyValue.createPropValue(inter.getIfOperStatus() + "", props[8]);
                /**
                 * 要利用到前一次的数据
                 */
                double sendUtilization = 0;
                double recieveUtilization = 0;
                List<Long> lastValue = lastValueMap.get(key);

                long speed = inter.getIfSpeed();
                long sendBytes = inter.getIfOutOctets();
                long recieveBytes = inter.getIfInOctets();
                if (speed == 0) {

                } else if (lastTime != null && lastValue != null) {
                    long interval = currentTime - lastTime;
                    sendUtilization = (sendBytes - lastValue.get(0)) * 1000d / interval / speed;
                    recieveUtilization = (recieveBytes - lastValue.get(1)) * 1000d / interval / speed;

                    /**
                     * 用新的数据替换前一次数据
                     */
                    lastValue.set(0, sendBytes);
                    lastValue.set(1, recieveBytes);
                } else {
                    List<Long> currentValue = new ArrayList<Long>(2);
                    currentValue.add(sendBytes);
                    currentValue.add(recieveBytes);
                    lastValueMap.put(key, currentValue);
                }
                values[6] = ResPropertyValue.createPropValue(DECIMAL_FORMAT.format(sendUtilization) + "", props[6]);
                values[7] = ResPropertyValue.createPropValue(DECIMAL_FORMAT.format(recieveUtilization) + "", props[7]);
            }

            /**
             * 更新时间
             */
            lastTime = currentTime;
        } catch (Exception e) {
            logger.error("网络设备：" + ip + "，端口采集失败", e);
            throw new CollectorException(e);
        } finally {
            if (snmp != null) {
                try {
                    snmp.close();
                } catch (Exception e2) {
                }
            }
        }
        return list;
    }
}
